package com.example.mq_sm.mqserver.core;

import lombok.Data;

import java.io.Serializable;
import java.util.UUID;

/**
 * 表示一个要传递的消息
 * 此处的 message 对象，是需要能够在网络上传输，并且也需要能写入到文件中
 * 此时就需要针对 message 进行序列化和反序列化
 * 此处使用 标准库 自带的 序列化/反序列化 操作
 * json 序列化是本质是文本，但此处的 message 是二进制数据所以需要使用标准库自带的
 */
@Data
// 实现的这个接口不需要重写相关方法，标志这个是可以进行序列化的
public class Message implements Serializable {

    // 用途是开发版本的
    // 在实际的开发中，代码是不断进行更新的，我将 message 类中的东西进行更改了 此时我如果
    // 将昨天的数据进行反序列化，则一定会出现问题
    // 所以引入了这个用来验证版本的东西
    // 当我需要进行修改的时候也要将这个版本号进行修改，然后在反序列化的时候先比对版本号
    // 如版本对不上则直接报错提醒
    private static final long serialVersionUID = 1L;

    // 这两个属性是 message 的核心属性
    private BasicProperties basicProperties = new BasicProperties();
    private byte[] body;

    // 下面的属性则是辅助用的属性
    // message 后续会存储到文件当中（如果持久化）
    // 一个文件中会存储很多的消息，如何找到某个消息，在文件中的具体位置
    // 使用下列的两个偏移量来进行表示 [offsetBeg, offsetEnd)

    // 这两个属性不需要被序列化保存到文件中，因为当消息被写入文件之后，所在位置就固定了，就可以直接找到
    // 这两个属性存在的目的，主要就是为了让内存中的 message 对象，能够快速找到对应的硬盘上的 message 的位置
    private transient long offsetBeg = 0; // 消息数据的开头距离文件开头的位置偏移（字节）
    private transient long offsetEnd = 0; // 消息数据的结尾距离文件开头的位置偏移（字节）
    // 使用这个属性表示该消息在文件中是否是有效信息->采用逻辑删除的方式
    // 0x1 表示有效。0x0 表示无效
    private byte isValid = 0x1;

    // 创建一个工厂方法，让工厂方法封装一下创建 message 对象的过程
    // 工厂方法相比于构造方法，多了一个可以进行自定义的方法名，有了这个方法名我们可以一目了然我们创建的对象包含的一些信息
    // 如果 routingKey 和 basicProperties 里的 routingKey 冲突，以外面的为主
    public static Message createMessageWithId(String routingKey, BasicProperties basicProperties, byte[] body){
        Message message = new Message();
        if (basicProperties != null){
            message.setBasicProperties(basicProperties);
        }
        // 此处生成的 messageId 以 M- 为前缀
        message.setMessageId("M-" + UUID.randomUUID());
        message.setRoutingKey(routingKey);
        message.body = body;
        // 此处先将这两个核心属性进行设置
        // 对于 offsetBeg 等属性属于持久化的时候才会用到，再把消息写入文件之前在进行设定
        // 此处知识设置一个 message 对象
        return message;
    }

    public String getMessageId(){
        return this.getBasicProperties().getMessageId();
    }

    public void setMessageId(String messageId){
        this.getBasicProperties().setMessageId(messageId);
    }

    public String getRoutingKey(){
        return this.getBasicProperties().getRoutingKey();
    }

    public void setRoutingKey(String routingKey){
        this.getBasicProperties().setRoutingKey(routingKey);
    }

    public int getDeliverMode(){
        return this.getBasicProperties().getDeliverMode();
    }

    public void setDeliverMode(int deliverMode){
        this.getBasicProperties().setDeliverMode(deliverMode);
    }


}
